// utils/websocket.js
export default class WebSocketManager {
  constructor(options = {}) {
    // 合并配置
    this.config = {
      url: '',
      heartInterval: 30000,     // 心跳间隔（毫秒）
      reconnectLimit: 5,        // 最大重连次数
      reconnectDelay: 5000,     // 重连基础间隔
      heartMsg: JSON.stringify({ type: 'ping' }), // 心跳消息
      ...options
    }

    // 内部状态
    this.socketTask = null      // WebSocket 实例
    this.reconnectTimes = 0     // 当前重连次数
    this.heartTimer = null      // 心跳定时器
    this.serverHeartTimer = null // 服务器心跳检测定时器
    this.isManualClose = false  // 是否手动关闭
    this.eventListeners = {}    // 事件监听器

    // 自动初始化
    this.connect()
	// 网络状态监听（构造函数末尾）
	this._initNetworkListener()
  }

  // 核心方法 --------------------------------------------------------
  
  // 建立连接
  connect() {
    // 清理旧连接
    if (this.socketTask) this.close()

    // 创建新连接
    this.socketTask = uni.connectSocket({
      url: this.config.url,
      success: () => this._handleConnectSuccess(),
      fail: err => this._handleConnectFail(err)
    })

    // 绑定事件
    this.socketTask.onOpen(() => this._handleOpen())
    this.socketTask.onMessage(msg => this._handleMessage(msg))
    this.socketTask.onClose(() => this._handleClose())
    this.socketTask.onError(err => this._handleError(err))
  }

  // 发送消息
  send(data) {
    if (this.socketTask && this.socketTask.readyState === 1) {
      const payload = typeof data === 'string' ? data : JSON.stringify(data)
      this.socketTask.send({ data: payload })
    } else {
      console.warn('WebSocket 未连接，消息发送失败')
      this._dispatchEvent('error', new Error('WebSocket not connected'))
    }
  }

  // 安全关闭
  close() {
	// 新增：移除网络监听
	// #ifdef MP-WEIXIN
	wx.offNetworkStatusChange?.()
	// #endif
    this.isManualClose = true
    this._clearTimers()
    if (this.socketTask) {
      this.socketTask.close()
      this.socketTask = null
    }
  }

  // 事件监听
  on(event, callback) {
    if (!this.eventListeners[event]) this.eventListeners[event] = []
    this.eventListeners[event].push(callback)
  }

  // 私有方法 --------------------------------------------------------

  // 触发事件
  _dispatchEvent(event, data) {
    const listeners = this.eventListeners[event]
    listeners?.forEach(fn => fn(data))
  }

  // 清理定时器
  _clearTimers() {
    clearTimeout(this.heartTimer)
    clearTimeout(this.serverHeartTimer)
  }

  // 启动心跳
  _startHeartbeat() {
    this.heartTimer = setInterval(() => {
      this.send(this.config.heartMsg)
      this._startServerHeartCheck() // 每次发送心跳后启动服务器检测
    }, this.config.heartInterval)
  }

  // 检测服务器心跳响应
  _startServerHeartCheck() {
    this.serverHeartTimer = setTimeout(() => {
      console.warn('服务器心跳超时，主动断开连接')
      this.close()
      this.reconnect()
    }, this.config.heartInterval + 2000) // 比心跳间隔多2秒容差
  }

  // 重连机制（指数退避）
  reconnect() {
    if (
      this.isManualClose ||
      this.reconnectTimes >= this.config.reconnectLimit
    ) return

    this.reconnectTimes++
    const delay = Math.min(
      this.config.reconnectDelay * Math.pow(2, this.reconnectTimes),
      30000 // 最大间隔30秒
    )

    setTimeout(() => {
      console.log(`第${this.reconnectTimes}次重连...`)
      this.connect()
    }, delay)
  }

  // 事件处理 --------------------------------------------------------
  
  _handleConnectSuccess() {
    console.log('WebSocket 连接初始化')
  }

  _handleConnectFail(err) {
    console.error('WebSocket 连接失败:', err)
    this._dispatchEvent('error', err)
    this.reconnect()
  }

  _handleOpen() {
    console.log('WebSocket 连接成功')
    this.reconnectTimes = 0
    this.isManualClose = false
    this._startHeartbeat()
    this._dispatchEvent('open')
  }

  _handleMessage(msg) {
    // 收到服务器心跳响应
    if (msg.data === 'pong') {
      clearTimeout(this.serverHeartTimer)
      return
    }

    try {
      const data = JSON.parse(msg.data)
      this._dispatchEvent('message', data)
    } catch (e) {
      this._dispatchEvent('message', msg.data)
    }
  }

  _handleClose() {
    console.log('WebSocket 连接关闭')
    this._clearTimers()
    this._dispatchEvent('close')

    if (!this.isManualClose) {
      this.reconnect()
    }
  }

  _handleError(err) {
    console.error('WebSocket 错误:', err)
    this._dispatchEvent('error', err)
    this.reconnect()
  }
  
  // 新增私有方法
  _initNetworkListener() {
    // 统一网络状态监听
    const handleNetworkChange = (res) => {
      if (res.isConnected && this.reconnectTimes > 0) {
        console.log('网络恢复，尝试重连')
        this.reconnect()
      }
    }
  
    // 各平台兼容处理
    // #ifdef H5 || APP
    uni.onNetworkStatusChange(handleNetworkChange)
    // #endif
  
    // 微信小程序特殊处理
    // #ifdef MP-WEIXIN
    wx.onNetworkStatusChange(handleNetworkChange)
    // #endif
  }
}